#!/usr/bin/env python
import string, os, sys, wx
import Sites
from stat import *

class SiteTree(wx.TreeCtrl):
    def __init__(self, parent, rootdir, OnUpdate):
        tID = wx.NewId()
        wx.TreeCtrl.__init__(self, parent, id=tID)
        self.parent = parent
        self.OnUpdate = OnUpdate
        self.rootdir = rootdir
        isz = (16,16)
        self.il = wx.ImageList(isz[0], isz[1])
        self.fldridx = self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_FOLDER,
                                                            wx.ART_OTHER, isz))
        self.SetImageList(self.il)
        root = self.AddRoot(rootdir)
        self.SetItemImage(root, self.fldridx, which=wx.TreeItemIcon_Normal)
        dirs = self.getDirs(rootdir)
        self.addLeaves(dirs, self.GetRootItem(), rootdir)
        self.Expand(self.GetRootItem())
        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnDirSelect, id=tID)
        self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnDirExpand, id=tID)
    
    def OnSize(self, evt):
        w, h = self.parent.GetClientSize()
        w = self.parent.GetSashPosition()
        self.SetSize((w, h))
    
    def getDirs(self, parentdir):
        if not os.path.exists(parentdir):
            return []
        return [d for d in os.listdir(parentdir) 
              if os.path.isdir(os.path.join(parentdir, d))
                  and d[0] != '.']
    
    def addLeaves(self, dirs, item, path):
        def hasDirs(dir):
            for d in os.listdir(dir):
                if os.path.isdir(os.path.join(dir, d)):
                    return True
            return False
        
        self.SetItemData(item, wx.TreeItemData(path))
        dirs.sort()
        for d in dirs:
            child = self.AppendItem(item, d)
            self.SetItemImage(child, self.fldridx, which=wx.TreeItemIcon_Normal)
            if hasDirs(os.path.join(path, d)):
                self.AppendItem(child, "")
        
    def OnDirSelect(self, evt):
        item = evt.GetItem()
        path = str(self.GetItemData(self.GetItemParent(item)).GetData())
        path = os.path.join(path, self.GetItemText(item))
        if os.path.exists(str(path)):
            self.OnUpdate(path)
    
    def OnDirExpand(self, evt):
        item = evt.GetItem()
        path = str(self.GetItemData(self.GetItemParent(item)).GetData())
        path = os.path.join(path, self.GetItemText(item))
        dirs = self.getDirs(path)
        if len(dirs) > 0:
            self.DeleteChildren(item)
            self.addLeaves(dirs, item, path)
        self.Refresh()
    
    def ExpandDir(self, dir):
        """
        Given a directory held within the tree, it will expand
        and set the relevant node as selected.
        """
        if os.path.isdir(dir):
            def doItem(node, cwd, dir):
                self.Expand(node)
                fc = self.GetFirstChild(node)
                while fc[0].IsOk():
                    twd = os.path.join(cwd, self.GetItemText(fc[0]))
                    # could use os.path.samefile(f1,f2) on Linux & Mac
                    if dir == twd:
                        return self.SelectItem(fc[0], True)
                    elif dir.startswith(twd) and dir[len(twd)] == os.sep:
                        self.Expand(fc[0])
                        return doItem(fc[0], twd, dir)
                    fc = self.GetNextChild(node, fc[1])
            root = self.GetRootItem()
            cwd = self.GetItemData(root).GetData()
            if dir.startswith(cwd):
                doItem(root, cwd, dir)
    
class SiteList(wx.ListCtrl):
    def __init__(self, parent, dir):   
        tID = wx.NewId() 
        wx.ListCtrl.__init__(self, parent, id=tID, style=wx.LC_REPORT |
                             wx.LC_SORT_DESCENDING)
        self.parent = parent
        self.InsertColumn(0, "Name")
        self.InsertColumn(1, "Owner")
        self.InsertColumn(2, "Full Name")
        self.refdct = {}
        self.populate(dir)
#        self.SetColumnWidth(0, wx.LIST_AUTOSIZE)
#        self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
#        self.SetColumnWidth(2, wx.LIST_AUTOSIZE)
        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)
    
    def SetExpandNotifier(self, OnExpandFct):
        self.ExpandDir = OnExpandFct
    
    def OnItemActivated(self, evt):
        currentItem = evt.m_itemIndex
        item = self.GetItem(currentItem)
        if hasattr(self, "ExpandDir"):
            self.ExpandDir(self.refdct.get(item.GetData()))
    
    def OnSize(self, evt):
        pw, h = self.parent.GetClientSize()
        w = pw - self.parent.GetSashPosition()
        self.SetSize((w, h))
    
    def populate(self, dir):
        self.DeleteAllItems()
        names = os.listdir(dir)
        imglst = wx.ImageList(16, 16)
        imglst.AddIcon(wx.Icon(" ", wx.ICON_ASTERISK))
        self.AssignImageList(imglst, 0)
        self.refdct = {}
        dct = {}
        i = 0
        for name in names:
            file = os.path.join(dir, name)
            mode = os.stat(file)[ST_MODE]
            perms = (file, oct(S_IMODE(mode)))[1]
            pic = 0
            if os.path.isdir(file):
                pic = 0
            dct[name] = (file, perms, i, pic)
            self.refdct[i] = file
            i += 1
        for (name, (file, perms, num, pic)) in dct.items():
                itm = wx.ListItem()
                itm.SetData(num)
                index = self.InsertItem(itm)
                self.SetStringItem(index, 0, name, pic)
                self.SetStringItem(index, 1, perms)
                self.SetStringItem(index, 2, file)
        self.SortItems(self.doSort)
    
    def doSort(self, one, two):
        one = self.refdct[one]
        two = self.refdct[two]
        if os.path.isdir(one) and os.path.isdir(two):
            if one == two:
                return 0
            elif one < two:
                return -1
            else:
                return 1
        elif os.path.isdir(one):
            return -1
        elif os.path.isdir(two):
            return 1
        else:
            if one == two:
                return 0
            elif one < two:
                return -1
            else:
                return 1
    
class ViewSite(wx.SplitterWindow):
    def __init__(self, parent, dir):
        tID = wx.NewId()
        wx.SplitterWindow.__init__(self, parent, id=tID,
                                   style=wx.SP_3D | wx.SP_LIVE_UPDATE)
        self.parent = parent
        w2 = SiteList(self, dir)
        w1 = SiteTree(self, dir, w2.populate)
        w2.SetExpandNotifier(w1.ExpandDir)
        self.SplitVertically(w1, w2, 160)
        self.SetMinimumPaneSize(100)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        
    def OnSize(self, evt):
        self.SetSize(self.parent.GetSize())
        self.GetWindow1().OnSize(None)
        self.GetWindow2().OnSize(None)
    
if __name__ == "__main__":
    app = wx.PySimpleApp()
    f = wx.Frame(None)
    st = ViewSite(f, "/var/www")
    f.Center()
    f.Show()
    app.MainLoop()
#isz = (16,16)GenericDirCtrlGenericDirCtrlGenericDirCtrl SplitTree
#il = wx.ImageList(isz[0], isz[1])
#fldridx = il.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz))
#fldropenidx = il.Add(wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER,
# isz))
#fileidx = il.Add(wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER,
# isz))
